﻿// #ifdef DEBUG
#include "guild_service_basic_context.h"

#include "ApplyJoinGuildArg_struct.h"
#include "ApplyJoinGuildRes_struct.h"
#include "ApproveJoinGuildArg_struct.h"
#include "ApproveJoinGuildRes_struct.h"
#include "ChangeGuildAnnounceArg_struct.h"
#include "ChangeGuildAnnounceRes_struct.h"
#include "ChangeGuildDeclarationArg_struct.h"
#include "ChangeGuildDeclarationRes_struct.h"
#include "ChangeGuildIconIdArg_struct.h"
#include "ChangeGuildIconIdRes_struct.h"
#include "ChangeGuildNameArg_struct.h"
#include "ChangeGuildNameRes_struct.h"
#include "CreateGuildArg_struct.h"
#include "CreateGuildRes_struct.h"
#include "KickOutGuildMemberArg_struct.h"
#include "KickOutGuildMemberRes_struct.h"
#include "QuitGuildArg_struct.h"
#include "QuitGuildRes_struct.h"
#include "SetAutoApprovalArg_struct.h"
#include "SetAutoApprovalRes_struct.h"
#include "SetGuildMemberDutyArg_struct.h"
#include "SetGuildMemberDutyRes_struct.h"

#include "LoginArg_struct.h"
#include "LoginRes_struct.h"
#include "LogoutNtfData_struct.h"
#include "GiveGuildItemArg_struct.h"
#include "GiveGuildItemRes_struct.h"

#include "box/service_context.hh"
#include "error/make_error_code.h"
#include "fwd.h"
#include "guild_service_basic.h"

#include "logic/guild_application_logic.h"
#include "logic/guild_basic_logic.h"
#include "logic/guild_brief_logic.h"
#include "logic/guild_members_logic.h"

#include "token/service_token_mgr.hpp"

namespace guild_service {
bool GuildServiceBasicContext::Start(kratos::service::ServiceContext *context) {
  if (!GuildServiceBasicContext::Init(context)) {
    LOG_FAIL("公会基础服务启动失败");
    return false;
  }

  return register_service(std::string(kGuildServicePrefix) + std::string(kGuildServiceBasicName));
}

bool GuildServiceBasicContext::Stop() {
  LOG_INFO("公会基础服务关闭");

  if (!unregister_service(std::string(kGuildServicePrefix) +
                          std::string(kGuildServiceBasicName))) {
    LOG_FAIL("公会基础服务关闭失败");
    return false;
  }

  return GuildServiceBasicContext::Uninit();
}

bool GuildServiceBasicContext::Init(kratos::service::ServiceContext *context) {
  if (!context) {
    return false;
  }

  if (!common::singleton_start<common::service_logger>(
          context, kGuildServiceBasicName)) {
    return false;
  }

  LOG_INFO("公会基础服务启动");

  if (!common::singleton_start<common::service_context>(context)) {
    LOG_FAIL("公会基础服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_redis_client>(context)) {
    LOG_FAIL("公会基础服务启动失败");
    return false;
  }

  std::string redis_host(kRedisHost);
  int32_t redis_port = kRedisPort;
  std::string redis_user(kRedisUser);
  std::string redis_passwd(kRedisPasswd);
  
  {  // config.redis
    auto *config_ptr = ServiceContextSingleton()->get_config().get_config_ptr();
    if (!config_ptr) {
      LOG_FAIL("公会认证服务启动失败");
      return false;
    }
    if (config_ptr->has("redis")) {
      if (config_ptr->has("redis.host")) {
        redis_host = config_ptr->getString("redis.host");
      }
      if (config_ptr->has("redis.port")) {
        redis_port = config_ptr->getInt32("redis.port");
      }
      if (config_ptr->has("redis.user")) {
        redis_user = config_ptr->getString("redis.user");
      }
      if (config_ptr->has("redis.passwd")) {
        redis_passwd = config_ptr->getString("redis.passwd");
      }
    }
  }
  if (!redis_add_host(kGuildServiceBasicName, redis_host, redis_port,
                      redis_user, redis_passwd)) {
    LOG_FAIL("公会基础服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::util>(context)) {
    LOG_FAIL("公会基础服务启动失败");
    return false;
  }

  return true;
}

bool GuildServiceBasicContext::Uninit() {
  return common::singleton_stop<common::service_redis_client>() &&
         common::singleton_stop<common::util>() &&
         common::singleton_stop<common::service_context>() &&
         common::singleton_stop<common::service_logger>();
}

void GuildServiceBasicContext::Tick(time_t ms) {
  common::singleton_update<common::service_redis_client>(ms);

  // 上一次加载公会模块的时间戳
  static time_t m_last_load_timestamp = 0;
  if (ms - m_last_load_timestamp > kLoadGuildModuleInterval) {
    m_last_load_timestamp = ms;

    // LOG_DEBUG("异步加载公会模块开始 当前时间戳:%lld ms", ms);
    GuildServiceBasicSingleton->LoadGuildAsync();
  }
}

void GuildServiceBasicContext::CreateGuild(
    rpc::StubCallPtr call, const CreateGuildArg &arg,
    std::shared_ptr<CreateGuildRes> &res) {

  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  guild_id_type guild_id = kInvalidGuildId;

  try {
    if (!GuildBasicLogic::CreateGuild(role_uuid, arg.name, guild_id, ec)) {
      LOG_WARN("创建公会失败 角色唯一id:%llu 公会id:%llu 错误:%s",
               role_uuid, guild_id, ec.message().c_str());
      res->result = static_cast<ErrorCode>(ec.value());
      return;
    }
  } catch (std::exception &ex) {
    LOG_EXCEPT("创建公会异常 异常:%s", ex.what());
    return;
  }

  LOG_INFO("创建公会成功 角色唯一id:%llu 公会id:%llu", role_uuid, guild_id);

  res->result = static_cast<ErrorCode>(ec.value());
  res->id = guild_id;
}

void GuildServiceBasicContext::ApplyJoinGuild(rpc::StubCallPtr call, 
    const ApplyJoinGuildArg &arg, std::shared_ptr<ApplyJoinGuildRes> &res) {
  
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (GuildBriefLogic::IsAutoApproval(arg.guild_id)) {
    if (!GuildMembersLogic::AddGuildMember(arg.guild_id, role_uuid, ec)) {
      LOG_WARN("加入公会成员失败 角色唯一id:%llu 公会id:%llu 错误:%s",
               role_uuid, arg.guild_id, ec.message().c_str());
      res->result = static_cast<ErrorCode>(ec.value());
      return;
    }
  } else {
    if (!GuildApplicationLogic::ApplyJoinGuild(
            role_uuid, arg.guild_id, guildservicebasic_cpp::RoleSex::ROLE_SEX_MALE,
            ec)) {
      LOG_WARN("申请加入公会失败 角色唯一id:%llu 公会id:%llu 错误:%s",
               role_uuid, arg.guild_id, ec.message().c_str());
      res->result = static_cast<ErrorCode>(ec.value());
      return;
    }
  }

  LOG_INFO("加入公会成员成功 角色唯一id:%llu 公会id:%llu", role_uuid,
           arg.guild_id);

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::KickOutGuildMember(rpc::StubCallPtr call, 
    const KickOutGuildMemberArg &arg,
    std::shared_ptr<KickOutGuildMemberRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildMembersLogic::KickOutGuildMember(role_uuid, arg.kick_role_uuid,
                                             ec)) {
    LOG_WARN("加入公会成员失败 角色唯一id:%llu 踢出成员角色唯一id:%llu 错误:%s",
             role_uuid, arg.kick_role_uuid, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  LOG_INFO("加入公会成员成功 角色唯一id:%llu 踢出成员角色唯一id:%llu",
           role_uuid, arg.kick_role_uuid);

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::SetAutoApproval(rpc::StubCallPtr call, 
    const SetAutoApprovalArg &arg, std::shared_ptr<SetAutoApprovalRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::SetAutoApproval(role_uuid, arg.is_auto_approval,
                                        ec)) {
    LOG_WARN("加入公会成员失败 角色唯一id:%llu 自动同意:%d 错误:%s",
             role_uuid, arg.is_auto_approval ? 1 : 0, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  LOG_INFO("加入公会成员成功 角色唯一id:%llu 自动同意:%d", role_uuid,
           arg.is_auto_approval ? 1 : 0);

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::QuitGuild(rpc::StubCallPtr call, const QuitGuildArg &arg,
                                         std::shared_ptr<QuitGuildRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  guild_id_type guild_id = kInvalidGuildId;
  // 公会剩余成员人数
  uint32_t member_left_count = 0;

  if (!GuildMembersLogic::QuitMember(role_uuid, guild_id, member_left_count,
                                     ec)) {
    LOG_WARN("退出公会失败 角色唯一id:%llu 公会id:%llu 错误:%s", role_uuid,
             guild_id, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  LOG_INFO("退出公会成功 角色唯一id:%llu 公会id:%llu", role_uuid, guild_id);

  if (member_left_count == 0) {
    if (!GuildBasicLogic::DeleteGuild(guild_id, ec)) {
      LOG_WARN("删除公会失败 角色唯一id:%llu 公会id:%llu 错误:%s",
               role_uuid, guild_id, ec.message().c_str());
      // res->result.value = 1;
      // res->result = guildservicebasic_cpp::ErrorCode::ERR_SUCCESS;
      res->result = static_cast<ErrorCode>(ec.value());
      return;
    }

    LOG_INFO("删除公会成功 角色唯一id:%llu 公会id:%llu", role_uuid,
             guild_id);
  }

  res->result = ErrorCode::ERR_SUCCESS;
}

void GuildServiceBasicContext::ChangeGuildIconId(rpc::StubCallPtr call, 
    const ChangeGuildIconIdArg &arg,
    std::shared_ptr<ChangeGuildIconIdRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::ChangeGuildIconIdByRole(role_uuid, arg.icon_id,
                                                ec)) {
    LOG_WARN("删除公会失败 角色唯一id:%llu 公会图标id:%u 错误:%s",
             role_uuid, arg.icon_id, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::ChangeGuildName(rpc::StubCallPtr call, 
    const ChangeGuildNameArg &arg, std::shared_ptr<ChangeGuildNameRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::ChangeGuildNameByRole(role_uuid, arg.name, ec)) {
    LOG_WARN("修改公会名称失败 角色唯一id:%llu 公会名字:%s 错误:%s", role_uuid,
             arg.name.c_str(), ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::ChangeGuildDeclaration(rpc::StubCallPtr call, 
    const ChangeGuildDeclarationArg &arg,
    std::shared_ptr<ChangeGuildDeclarationRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::ChangeGuildDeclarationByRole(role_uuid,
                                                     arg.declaration, ec)) {
    LOG_WARN("删除公会失败 角色唯一id:%llu 公会宣言:%s 错误:%s", role_uuid,
             arg.declaration.c_str(), ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::ChangeGuildAnnounce(rpc::StubCallPtr call, 
    const ChangeGuildAnnounceArg &arg,
    std::shared_ptr<ChangeGuildAnnounceRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::ChangeGuildAnnounceByRole(role_uuid, arg.announce,
                                                  ec)) {
    LOG_WARN("删除公会失败 角色唯一id:%llu 公会通知:%s 错误:%s", role_uuid,
             arg.announce.c_str(), ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::ApproveJoinGuild(rpc::StubCallPtr call, 
    const ApproveJoinGuildArg &arg, std::shared_ptr<ApproveJoinGuildRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildApplicationLogic::ApproveJoinGuild(role_uuid,
                                               arg.apply_role_uuid, ec)) {
    LOG_WARN(
        "同意加入公会失败 角色唯一id:%llu 申请加入的角色唯一id:%llu 错误:%s",
        role_uuid, arg.apply_role_uuid, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::SetGuildMemberDuty(rpc::StubCallPtr call, 
    const SetGuildMemberDutyArg &arg,
    std::shared_ptr<SetGuildMemberDutyRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildMembersLogic::SetMemberDuty(
          role_uuid, arg.member_role_uuid, arg.duty, ec)) {
    LOG_WARN("设置公会成员职责失败 角色唯一id:%llu 成员角色唯一id:%llu 错误:%s",
             role_uuid, arg.member_role_uuid, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBasicContext::Login(rpc::StubCallPtr call, const LoginArg &arg,
                                     const std::shared_ptr<LoginRes> &res) {
  res->result = ErrorCode::ERR_SUCCESS;
}

void GuildServiceBasicContext::Logout(rpc::StubCallPtr call, const LogoutNtfData &data) {
}

void GuildServiceBasicContext::GiveGuildItem(rpc::StubCallPtr call, const GiveGuildItemArg &arg,
                            std::shared_ptr<GiveGuildItemRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBasicName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildBriefLogic::GiveGuildItem(
          role_uuid, arg.item_id, arg.item_count, ec)) {
    LOG_WARN("上交公会道具失败 角色唯一id:%llu 道具id:%u 道具数量:%u 错误:%s",
             role_uuid, arg.item_id, arg.item_count, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }
  res->result = static_cast<ErrorCode>(ec.value());
}


};  // namespace guild_service

// #endif // DEBUG